import psutil
from time import sleep

from uiautomation import Control

from penguin import auto, logging
from penguin.subscription import SubscriptionCollection
from penguin.window import Window
from penguin.utils import ListUtils
from penguin.friend import FriendDialog
from penguin.wechatlogin import WechatLogin
from penguin.officialaccount import OfficialAccount

class Wechat(Window):
    """
    Wechat类型实例代表微信主窗口。
    """

    def __init__(self):
        """
        初始化实例。
        """ 
        super().__init__('微信', '主窗口', 'WeChatMainWndForPC')        

    def __wakeup_with_shortcut(self, key_1:str='Ctrl', key_2:str='Alt', key_3:str='W'):
        """
        使用热键组合方式唤醒微信到桌面。

        参数：
            key_1 热键组合中按键1，默认值为。
            key_2 热键组合中按键2，默认值为。
            key_3 热键组合中按键3，默认值为。
        返回：
            成功返回True否则返回False
        """
        #要使用SendKeys方法而不是Sendkey方法。
        auto.SendKeys('{%s}{%s}(%s)'%(key_1, key_2, key_3))
        logging.info('使用热键组合(%s + %s + %s)唤醒 微信主窗口。' % (key_1, key_2, key_3))
        self.window.SetFocus()

    def is_running(self, p_name='WeChat')-> bool:
        pids: list[int] = psutil.pids()
        for pid in pids:
            process = psutil.Process(pid)
            if process.name().find(p_name) > -1:
                return True
        return False

    def is_logged_in(self)-> bool:
        pass
    
    def show_on_desk(self)-> bool:
        """
        将微信主窗口显示在系统桌面并与其连接。

        返回：
            成功获取返回True否则返回False
        """
        if self.is_on_desk():
            # 微信窗口在桌面而不在最上层时把窗口调整至最上层。
            self.window.SetFocus()
            logging.info('微信主窗口 已经显示在系统桌面。')
            return True
        try:
            # 使用热键组合来唤醒微信。
            self.__wakeup_with_shortcut()
            logging.info('微信主窗口 已经被成功唤醒，显示在系统桌面。')
            return True
        except LookupError as e:
            # 再次唤醒微信失败可能是微信未启动，尝试启动微信。
            # todo 1.自动登陆时程序目录不应该硬编码。2.等待微信主窗口是否加载成功不应该为固定等待值，应该将此功能交给WechatLogin类。
            logging.warning('微信主窗口 唤醒失败，尝试运行微信程序并且自动登录。')
            WechatLogin().run_and_login('D:\\Tencent\\WeChat\\WeChat.exe')
            sleep(10)
            return self.is_on_desk()
    
    def __filter_item_by_name(self, controls:list[Control], name:str)-> Control:
        """
        在搜索结果列表中过虑出包含指定文本的列表项控件。

        参数：
            controls 搜索结果列表。
            name 指定的文本。
        返回：
            包含指定文本的控件。
        """
        name = '<em>%s</em>' % name
        for control in controls:
            if control.TextControl().Name == name:
                logging.info('在 微信主窗口 搜索结果列表中找到 %s 。' % name)
                return control
        logging.info('在 微信主窗口 搜索结果列表中没有找到 %s 。' % name)
        return None
        
    def find_entrance(self, name:str)-> Control:
        """
        在窗口中使用名字搜索好友或公众号入口控件。

        参数：
            name 要查找好友或公众号名称。
        返回：
            指定的好友或公众号入口控件。
        """
        if self.show_on_desk():
            try:
                book = self.window.ToolBarControl(searchDepth=4, Name='导航').GetNextSiblingControl()
                search = book.GetChildren()[0]
                search_edit = search.EditControl(searchDepth=4, Name='搜索')
                search_edit.Click()
                search_edit.SendKeys(name, interval=0.5)
                # 等待搜索完成显示结果列表。
                sleep(1)
                results = book.ListControl(SubName='SEARCH_RESULT')
                control = self.__filter_item_by_name(results.GetChildren(), name)
                ListUtils.show_item_in_list(results, control)
                if name == '订阅号' and control != None:
                    control.Click()
                    conversation = book.GetChildren()[1].ListControl(searchDepth=4, name='会话')
                    for entrance in conversation.GetChildren():
                        if entrance.Name == '订阅号':
                            auto.RightClick(entrance.BoundingRectangle.xcenter(), entrance.BoundingRectangle.ycenter())
                            sleep(0.5)
                            break
                    return self.window.MenuControl(searchDepth=1).MenuItemControl(SubName='在独立窗口中打开')  
                else:
                    return control
            except LookupError as e:
                if e.args[0].find('导航') >= 0:
                    logging.error('查找不到 导航 元素，微信界面结构是否修改。')
                if e.args[0].find('搜索') >= 0:
                    logging.error('查找不到 搜索 元素，微信界面结构是否修改。')
                if e.args[0].find('SEARCH_RESULT') >= 0:
                    logging.error('查找不到 SEARCH_RESULT 元素，微信界面结构是否修改。')
            except Exception as e:
                logging.error('按名称搜索 公众号 或 好友 时出错 %s。' % e.arg[0])
        else:
            logging.error('按名称搜索 公众号 或 好友 时出错 %s。' % e.arg[0])
            return None
        
    def open_subscription_collection(self):
        """
        在微信主窗口打开订阅号窗口。

        返回：
            订阅号窗口。
        """       
        return self.open_new_window('订阅号','SubscriptionWnd', SubscriptionCollection)
        
    def open_official_account(self, name:str)-> OfficialAccount:
        """
        在微信主窗口打开指定公众号窗口。

        参数：
            name 要查找公众号名称。
        返回：
            指定的公众号窗口。
        """
        return self.open_new_window(name, 'ChatWnd', OfficialAccount)
        
    def open_friend(self, name:str)-> FriendDialog:
        """
        在微信主窗口打开指定好友对话窗口。

        参数：
            name 要查找好友名称。
        返回：
            指定的好友对话窗口。
        """
        return self.open_new_window(name, self.class_name, FriendDialog)